(* MAP *)

let rec map f list = match list with
  | [] -> []
  | h::t -> f h::map f t ;;

(* ITER *)

let rec iter f list = match list with
  | [] -> () 
  | h::t -> f h; iter f t ;;
iter (print_int) [1;3;5;7;11] ;;

(* FOR_ALL *)

let rec for_all f list = match list with
  | [] -> true
  | h::t -> f h && for_all f t ;; 
for_all (function x -> x=0) [0; 0; 0; 0; 0] ;;

(* PRINT_LIST_CHAR *)

let print_list_char list = iter (print_char) list ;;
print_list_char ['R'; 'T'; 'F'; 'F'] ;;

(* UPPER *)

open Char ;;

let upper list = map (uppercase) list ;;
upper ['p'; '0'; 'T'] ;;

(* DOUBLE *)

let rec double (f:int -> int) list = map f (map f list) ;;

(* DIV_ZERO *)

let div_zero list = for_all (function (a, b) -> b<>0) list ;;
div_zero [(2, 1); (5, 2)] ;;

(* PRINT_LISTLIST_INT *)

let print_listlist_int list =  iter (function l -> iter (function x -> print_int x; print_string " ") l; print_string "\n") list ;;
print_listlist_int [[1;2;3;5]; [2;5;6;8;7]] ;;

(* ROTN *)

let rec rotn n list =
  if n < 0 then
    rotn (n+26) list
  else if n > 26 then
    rotn (n-26) list
  else
    let rec remplace n a =
      match code(a) with  
	| x when x > 96 && x + n < 123 -> chr(x + n)
	| x when x > 96 && x < 123     -> chr(x + n - 26)
	| x when x > 64 && x + n  < 91 -> chr(x + n)
	| x when x > 64 && x < 91      -> chr(x + n - 26)
	| x -> a
    in
    map (remplace n) list ;;
 
rotn 5 ['a'; 'y'; 'Z'; '0'; '?'] ;;			  
			 
(* EXCHANGE_CHAR *)

let exchange_char c1 c2 list =
  let remplace c1 c2 a = match a with
    | a when a=c1 -> c2
    | a ->
      if a=c2 then
        c1
      else a
  in
    map (remplace c1 c2) list ;; 
exchange_char 'a' 'b' ['a'; 'b'; 'a'] ;;

 (* BRUTE_ROT *)

let brute_rot list =
  let rec rec_brute_rot l n = match n with
    | n when n<26 -> print_list_char (rotn n l); print_string "\n"; rec_brute_rot l (n+1)
    | _ -> ()
  in
    rec_brute_rot list 1 ;;

let my_secret = ['Z'; 'u'; ' '; 'c'; 'q'; 'y'; 'j'; 'h'; 'y'; 'i'; 'u'; ' '; 'b'; '\''; 'e'; 't'; 'h'; 'u'; ' '; 'i'; 'k'; 'k'; 'f'; 'u'; 'h'; 'y'; 'u'; 'k'; 'h'] ;;
brute_rot my_secret ;;

(* FMAP *)

let rec fmap list_f list = match list_f with
  | f::[] -> map f list 
  | f::l ->fmap l (map f list)
  | ;;

let mysecret_list = ['C';'y';'b';'z';'b';'l';'c';'n';'v';'y';'r';'l';':';'l';'c';'y';'b';'z';'b';'l';'q';'r';'l';'e';'\'';'r';'p';'u';'r';'p'];;
fmap [rotn 5; exchange_char 'w' 'q'; rotn 18; exchange_char ' ' 'v'; rotn 42] mysecret_list ;;
